package com.cn.lp.jpa.cq.test.domain;

import javax.validation.constraints.NotNull;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 *
 */
public abstract class ScheduleTask<TTrigger extends TaskTrigger> implements Comparable<ScheduleTask> {

    private String name;
    private AtomicBoolean mark = new AtomicBoolean(false);
    private TTrigger trigger;

    public ScheduleTask(String name, TTrigger trigger) {
        this.name = name;
        this.trigger = trigger;
    }

    public boolean canExec() {
        return trigger.canTrigger();
    }

    protected void setTrigger(TTrigger trigger) {
        this.trigger = trigger;
    }

    //    public Optional<Long> getNextTime() {
//        return Optional.ofNullable(trigger.getNextTriggerTime());
//    }
//
//    public Optional<Long> getNextTime(long currentTime) {
//        return Optional.ofNullable(trigger.getTriggerTimeAfter(currentTime));
//    }

    public void cancelMark() {
        this.mark.set(false);
    }

    public boolean mark() {
        return this.mark.compareAndSet(false, true);
    }

    public String getName() {
        return name;
    }


    public final void exec() {
        preExec();
        doExec();
        postExec();
    }

    protected void preExec() {
    }

    protected void postExec() {
    }

    protected abstract void doExec();

    protected TTrigger getTrigger() {
        return trigger;
    }

    protected void triggerNextTime(long executeTime) {
        preTrigger(executeTime, trigger);
        trigger.trigger(executeTime);
        postTrigger(executeTime, trigger);
    }

    protected void preTrigger(long executeTime, TTrigger trigger) {
    }

    protected void postTrigger(long executeTime, TTrigger trigger) {
    }

    @Override
    public int compareTo(@NotNull ScheduleTask o) {
        if (Objects.isNull(o)) {
            return 0;
        }
        // 容错，如果计算失败，则拿当前时间计算
        long currentTime = System.currentTimeMillis();
        Long nextTime = trigger.getNextTriggerTime().orElse(currentTime);
        Long targetNextTime = o.trigger.getNextTriggerTime().orElse(currentTime);
        return nextTime.compareTo(targetNextTime);
    }

}
